package com.random;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;

/**
 * 测试红包生成
 * 
 * @author yaojinshan
 * @since 2018-04-10 14:27
 */
public class TestRedpacket2 {
	static int MAX = 100 * 100;// 最大金额
	static int MIN = 1;// 最小金额
	static double TIMES = 2.0d;// 红包平均值的倍率
	static int MONEY = 50000;// 待分金额
	static int COUNT = 100;// 数量

	public static void main(String[] args) {
		if (!isRight(COUNT, MONEY)) {
			throw new RuntimeException("给定的红包数额和数量不能满足最大或者最小需求！");
		}
		// 平均值  * 倍率 的值  用来规范  红包的大小
		int maxS = (int) ((TIMES * MONEY) / COUNT);
		System.out.println("maxS:" + maxS);
		List<Integer> list = new ArrayList<Integer>();
		int one = 0;
		int maxOne = 0;
		int minOne = 0;
		for (int i = 0; i < COUNT; i++) {
			one = random(MONEY, COUNT-i,MIN,maxS);
			list.add(one);
			if(i == 0){
				minOne = one;
			}else if(one < minOne){
				minOne = one;
			}else if(one > maxOne){
				maxOne = one;
			}
			MONEY = MONEY - one;
		}
		System.out.println("minOne:" + minOne);
		System.out.println("maxOne:" + maxOne);
		System.out.println(JSON.toJSONString(list));
	}
	/**
	 * 随机生成红包的值
	 * @param money 剩余金额
	 * @param count 剩余数量
	 * @param minS 最小值
	 * @param maxS 最大值
	 * @return
	 */
	static int random(int money, int count, int minS, int maxS){
		//最后一个红包包揽所有金额
		if(count == 1){
			return money;
		}
		//最大金额  * 倍率的值 保证 该值不能大于剩下的总金额
		int max = maxS > money ? money : maxS;
		//生成一个随机红包  此时 % max 对 max 求余 保证了 one 不会超过maxS
		int one = (int) (Math.rint(Math.random() * (max - minS) + minS) % max) + 1;
		//如果剩下的数量 和  剩下的钱 满足要求  则返回红包的值 否则递归生成
		if(isRight(count - 1, money - one)){
			return one;
		}else{
			double avg = (money - one) / (count - 1);//计算当前随机数下 剩下的红包情况
			if(avg > MAX){
				//如果平均值大于最大金额  说明本次生成红包太小，此时需要扩大原有区间的左区间的值 比如 从[1,100) 变为[10,100) 来提高生成红包的大小
				one = random(money, count, one, maxS);
			}else{ 
				//如果平均值小于 最小金额  说明本次生成红包太大，此时需要降低原有区间的右区间的值 比如 从[1,100) 变为[1,50) 来缩小生成红包的大小
				one = random(money, count, minS, one);
			}
		}
		return one;
	}

	/**
	 * 检测当前红余额和数量是否满足 最大值 最小值条件
	 * 
	 * @param count
	 *            剩余数量
	 * @param money
	 *            剩余金额
	 * @return
	 */
	static boolean isRight(int count, int money) {
		double avg = money / count;
		if (MIN > avg || MAX < avg) {
			return false;
		}
		return true;
	}

}
